using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

namespace CollabApp.Domain.Entities.Game;

/// <summary>
/// 游戏玩家实体类 - 记录单个玩家在特定游戏中的表现和统计数据
/// 用于存储玩家的游戏过程数据、最终成绩、排名等信息
/// </summary>
[Table("game_players")]
public class GamePlayer : BaseEntity
{
    /// <summary>
    /// 游戏ID - 关联到具体的游戏实例
    /// </summary>
    [Required]
    [Column("game_id")]
    public Guid GameId { get; private set; }

    /// <summary>
    /// 用户ID - 关联到参与游戏的用户
    /// </summary>
    [Required]
    [Column("user_id")]
    public Guid UserId { get; private set; }

    /// <summary>
    /// 玩家颜色 - 在游戏中代表该玩家的颜色标识
    /// 格式：十六进制颜色值，例如 "#FF0000"
    /// </summary>
    [Required]
    [MaxLength(7)]
    [Column("player_color")]
    public string PlayerColor { get; private set; } = string.Empty;

    /// <summary>
    /// 最终占地面积 - 游戏结束时玩家占据的总面积
    /// 用于计算排名和积分，精确到小数点后2位
    /// </summary>
    [Column("final_area")]
    [Precision(10, 2)]
    public decimal FinalArea { get; private set; } = 0;

    /// <summary>
    /// 最终排名 - 玩家在该局游戏中的最终名次
    /// 数值越小排名越高，null表示未完成游戏
    /// </summary>
    [Column("final_rank")]
    public int? FinalRank { get; private set; }

    /// <summary>
    /// 积分变化 - 本局游戏对玩家总积分的影响
    /// 正数表示积分增加，负数表示积分减少
    /// </summary>
    [Column("score_change")]
    public int ScoreChange { get; private set; } = 0;

    /// <summary>
    /// 操作次数 - 玩家在游戏过程中执行的操作总数
    /// 用于统计玩家活跃度和游戏参与度
    /// </summary>
    [Column("actions_count")]
    public int ActionsCount { get; private set; } = 0;

    /// <summary>
    /// 游戏时长 - 玩家在该局游戏中的实际参与时间（秒）
    /// 用于统计玩家的游戏投入度和活跃时间
    /// </summary>
    [Column("play_time")]
    public int PlayTime { get; private set; } = 0;

    /// <summary>
    /// 玩家出生点X坐标
    /// </summary>
    [Column("spawn_x")]
    public float SpawnX { get; private set; } = 0f;

    /// <summary>
    /// 玩家出生点Y坐标
    /// </summary>
    [Column("spawn_y")]
    public float SpawnY { get; private set; } = 0f;

    /// <summary>
    /// 当前位置X坐标
    /// </summary>
    [Column("position_x")]
    public float PositionX { get; private set; } = 0f;

    /// <summary>
    /// 当前位置Y坐标
    /// </summary>
    [Column("position_y")]
    public float PositionY { get; private set; } = 0f;

    /// <summary>
    /// 玩家状态 - Alive(存活)、Dead(死亡)、Respawning(复活中)
    /// </summary>
    [Column("status")]
    public PlayerStatus Status { get; private set; } = PlayerStatus.Alive;

    /// <summary>
    /// 死亡次数
    /// </summary>
    [Column("death_count")]
    public int DeathCount { get; private set; } = 0;

    /// <summary>
    /// 击杀数量（截断其他玩家次数）
    /// </summary>
    [Column("kill_count")]
    public int KillCount { get; private set; } = 0;

    /// <summary>
    /// 最大历史领地面积
    /// </summary>
    [Column("max_territory_area")]
    [Precision(10, 2)]
    public decimal MaxTerritoryArea { get; private set; } = 0;

    /// <summary>
    /// 当前持有的道具类型
    /// </summary>
    [Column("current_powerup")]
    public string? CurrentPowerUp { get; private set; }

    /// <summary>
    /// 道具使用次数
    /// </summary>
    [Column("powerup_usage_count")]
    public int PowerUpUsageCount { get; private set; } = 0;

    /// <summary>
    /// 复活时间戳（用于计算无敌时间）
    /// </summary>
    [Column("respawn_timestamp")]
    public long? RespawnTimestamp { get; private set; }

    /// <summary>
    /// 团队ID（团队模式使用）
    /// </summary>
    [Column("team_id")]
    public int? TeamId { get; private set; }

    // ============ 构造函数 ============

    /// <summary>
    /// 无参构造函数 - EF Core 必需
    /// </summary>
    private GamePlayer() { }

    /// <summary>
    /// 私有构造函数 - 仅限工厂方法调用
    /// </summary>
    /// <param name="gameId">游戏ID</param>
    /// <param name="userId">用户ID</param>
    /// <param name="playerColor">玩家颜色</param>
    private GamePlayer(Guid gameId, Guid userId, string playerColor)
    {
        GameId = gameId;
        UserId = userId;
        PlayerColor = playerColor;
        FinalArea = 0;
        FinalRank = null;
        ScoreChange = 0;
        ActionsCount = 0;
        PlayTime = 0;
    }

    // ============ 导航属性 ============
    
    /// <summary>
    /// 导航属性 - 关联的游戏实例
    /// </summary>
    [ForeignKey("GameId")]
    public virtual Game Game { get; set; } = null!;
    
    /// <summary>
    /// 导航属性 - 关联的用户信息
    /// </summary>
    [ForeignKey("UserId")]
    public virtual Auth.User User { get; set; } = null!;

    // ============ 工厂方法 ============

    /// <summary>
    /// 创建游戏玩家记录 - 工厂方法
    /// </summary>
    /// <param name="gameId">游戏ID</param>
    /// <param name="userId">用户ID</param>
    /// <param name="playerColor">玩家颜色</param>
    /// <param name="spawnX">出生点X坐标</param>
    /// <param name="spawnY">出生点Y坐标</param>
    /// <param name="teamId">团队ID（可选）</param>
    /// <returns>新的游戏玩家实例</returns>
    public static GamePlayer CreateGamePlayer(Guid gameId, Guid userId, string playerColor, 
                                              float spawnX = 0f, float spawnY = 0f, int? teamId = null)
    {
        if (gameId == Guid.Empty)
            throw new ArgumentException("游戏ID不能为空", nameof(gameId));
        if (userId == Guid.Empty)
            throw new ArgumentException("用户ID不能为空", nameof(userId));
        if (string.IsNullOrWhiteSpace(playerColor))
            throw new ArgumentException("玩家颜色不能为空", nameof(playerColor));

        var player = new GamePlayer(gameId, userId, playerColor);
        player.SetSpawnPoint(spawnX, spawnY);
        player.TeamId = teamId;
        return player;
    }

    // ============ 业务方法 ============

    /// <summary>
    /// 更新游戏结果
    /// </summary>
    /// <param name="finalArea">最终占地面积</param>
    /// <param name="finalRank">最终排名</param>
    /// <param name="scoreChange">积分变化</param>
    /// <param name="playTime">游戏时长</param>
    public void UpdateGameResult(decimal finalArea, int finalRank, int scoreChange, int playTime)
    {
        if (finalArea < 0)
            throw new ArgumentException("占地面积不能为负数", nameof(finalArea));
        if (finalRank <= 0)
            throw new ArgumentException("排名必须大于0", nameof(finalRank));

        FinalArea = finalArea;
        FinalRank = finalRank;
        ScoreChange = scoreChange;
        PlayTime = Math.Max(0, playTime);
    }

    /// <summary>
    /// 增加操作次数
    /// </summary>
    /// <param name="count">增加的次数</param>
    public void IncrementActions(int count = 1)
    {
        ActionsCount += Math.Max(0, count);
    }

    /// <summary>
    /// 检查是否为获胜者
    /// </summary>
    /// <returns>是否为第一名</returns>
    public bool IsWinner() => FinalRank == 1;

    /// <summary>
    /// 获取积分变化类型
    /// </summary>
    /// <returns>积分变化描述</returns>
    public string GetScoreChangeType()
    {
        return ScoreChange switch
        {
            > 0 => "积分增加",
            < 0 => "积分减少",
            _ => "积分无变化"
        };
    }

    /// <summary>
    /// 设置出生点
    /// </summary>
    /// <param name="x">X坐标</param>
    /// <param name="y">Y坐标</param>
    public void SetSpawnPoint(float x, float y)
    {
        SpawnX = x;
        SpawnY = y;
        PositionX = x;
        PositionY = y;
    }

    /// <summary>
    /// 更新玩家位置
    /// </summary>
    /// <param name="x">新X坐标</param>
    /// <param name="y">新Y坐标</param>
    public void UpdatePosition(float x, float y)
    {
        if (Status != PlayerStatus.Alive) return;
        PositionX = x;
        PositionY = y;
    }

    /// <summary>
    /// 玩家死亡
    /// </summary>
    /// <param name="timestamp">死亡时间戳</param>
    public void Die(long? timestamp = null)
    {
        Status = PlayerStatus.Dead;
        DeathCount++;
        CurrentPowerUp = null;
        
        // 保留20%的最大历史领地面积作为"领地记忆"积分
        if (FinalArea > MaxTerritoryArea)
        {
            MaxTerritoryArea = FinalArea;
        }
        FinalArea = MaxTerritoryArea * 0.2m;
    }

    /// <summary>
    /// 开始复活
    /// </summary>
    /// <param name="timestamp">复活开始时间戳</param>
    public void StartRespawn(long? timestamp = null)
    {
        Status = PlayerStatus.Respawning;
        RespawnTimestamp = timestamp ?? DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
        PositionX = SpawnX;
        PositionY = SpawnY;
    }

    /// <summary>
    /// 复活完成
    /// </summary>
    public void CompleteRespawn()
    {
        Status = PlayerStatus.Alive;
        RespawnTimestamp = null;
    }

    /// <summary>
    /// 击杀其他玩家
    /// </summary>
    public void RecordKill()
    {
        KillCount++;
    }

    /// <summary>
    /// 拾取道具
    /// </summary>
    /// <param name="powerUpType">道具类型</param>
    public void PickUpPowerUp(string powerUpType)
    {
        if (string.IsNullOrWhiteSpace(powerUpType)) return;
        CurrentPowerUp = powerUpType;
    }

    /// <summary>
    /// 使用道具
    /// </summary>
    public void UsePowerUp()
    {
        if (CurrentPowerUp != null)
        {
            PowerUpUsageCount++;
            CurrentPowerUp = null;
        }
    }

    /// <summary>
    /// 检查是否处于无敌状态
    /// </summary>
    /// <returns>是否无敌</returns>
    public bool IsInvincible()
    {
        if (Status != PlayerStatus.Alive || RespawnTimestamp == null)
            return false;

        var elapsed = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - RespawnTimestamp.Value;
        return elapsed < 5000; // 5秒无敌时间
    }

    /// <summary>
    /// 检查是否完全无敌（前3秒）
    /// </summary>
    /// <returns>是否完全无敌</returns>
    public bool IsFullyInvincible()
    {
        if (Status != PlayerStatus.Alive || RespawnTimestamp == null)
            return false;

        var elapsed = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - RespawnTimestamp.Value;
        return elapsed < 3000; // 前3秒完全无敌
    }

    /// <summary>
    /// 获取KD比率
    /// </summary>
    /// <returns>击杀死亡比</returns>
    public decimal GetKDRatio()
    {
        return DeathCount == 0 ? KillCount : (decimal)KillCount / DeathCount;
    }

    /// <summary>
    /// 更新领地面积
    /// </summary>
    /// <param name="area">新的领地面积</param>
    public void UpdateTerritoryArea(decimal area)
    {
        FinalArea = Math.Max(0, area);
        if (FinalArea > MaxTerritoryArea)
        {
            MaxTerritoryArea = FinalArea;
        }
    }
}

/// <summary>
/// 玩家状态枚举
/// </summary>
public enum PlayerStatus
{
    /// <summary>
    /// 存活状态
    /// </summary>
    Alive,
    
    /// <summary>
    /// 死亡状态
    /// </summary>
    Dead,
    
    /// <summary>
    /// 复活中状态
    /// </summary>
    Respawning
}
